package com.storm.queue.core

import com.storm.queue.model.QueueProperties
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.data.redis.connection.RedisConnectionFactory
import org.springframework.data.redis.core.RedisTemplate
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer
import org.springframework.data.redis.serializer.StringRedisSerializer
import org.springframework.stereotype.Component
import com.fasterxml.jackson.databind.ObjectMapper
import com.storm.queue.RedisDelayOperation
import com.storm.queue.QueueApi
import com.storm.queue.RedisKeyUtil
import com.storm.queue.RedisLock

@Component
@EnableConfigurationProperties(QueueProperties::class)
class QueueConfiguration {

    @Bean
    @ConditionalOnMissingBean(RedisTemplate::class)
    fun redisTemplate(redisConnectionFactory: RedisConnectionFactory): RedisTemplate<String, Any> {
        val redis = RedisTemplate<String, Any>()
        redis.setConnectionFactory(redisConnectionFactory)
        val stringRedisSerializer = StringRedisSerializer()
        redis.keySerializer = stringRedisSerializer
        val jackson2JsonRedisSerializer = Jackson2JsonRedisSerializer(Any::class.java)
        jackson2JsonRedisSerializer.setObjectMapper(ObjectMapper())
        redis.valueSerializer = jackson2JsonRedisSerializer
        redis.hashKeySerializer = stringRedisSerializer
        redis.hashValueSerializer = jackson2JsonRedisSerializer
        redis.afterPropertiesSet()
        return redis
    }

    @Bean
    @ConditionalOnMissingBean(ObjectMapper::class)
    fun objectMapper() = ObjectMapper()

    @Bean
    @ConditionalOnMissingBean(DelayOperation::class)
    fun delayOperation(queueProperties: QueueProperties, objectMapper: ObjectMapper, redisTemplate: RedisTemplate<String, Any>): DelayOperation {
        return RedisDelayOperation(redisTemplate,
                RedisKeyUtil(queueProperties.objectName),
                objectMapper, RedisLock(redisTemplate))
    }

    @Bean
    fun queueApi(operation: DelayOperation):QueueApi{
        return QueueApi(operation)
    }

    @Bean
    fun queueRun(operation: DelayOperation):QueueRun{
        return QueueRun(DelayQueueContext(operation))
    }



}